from car import Car
# 9.1.1
# 如果要进行面向对象的编程(object-oriented programming (OOP))
# 应该编写表示现实世界中的事物和情景的类(class)，
# 并基于这些类来创建对象(object)
# 创建一个类
# 说明：
#     1、下面的类中__init__()方法
#     2、使用__init__()方法，并不等同于创建了一个列表，给列表赋初值
"""
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def sit(self):
        print(f"{self.name} is now sitting.")

    def roll_over(self):
        print(f"{self} rolled over!")
"""

# 9.1.2-1
# 使用类时，类中会定义一些函数，
# 这些函数可以在外面创建一个特定的对象之后，对这个特定的对象进行方法的调用
# 而这个方法对应这个类中的函数
# 可以将类是为有关如何创建实例的说明
# 实际上每个类都需要有__init__()这个函数
# 这个函数就说明了要创建这个实例 需要给入哪些参数
"""
my_dog = Dog('Willie', 6)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
my_dog.sit()
"""

# 9.1后的动手试一试
# 练习9.1
"""
class Restaurant:
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type

    def describe_restaurant(self):
        print(f"{self.restaurant_name} is a restaurant with {self.cuisine_type}.")

    def open_restaurant(self):
        print(f"{self.restaurant_name} is opening now!")


favoriteRestaurant = Restaurant('Lao Shi Hui', 'fish and prawns podjarka')
favoriteRestaurant.describe_restaurant()
favoriteRestaurant.open_restaurant()
"""

# 练习9.2
"""
Restaurant_one = Restaurant('Huo Shao Yun', 'yun nan mushrooms')
Restaurant_one.describe_restaurant()
Restaurant_two = Restaurant('Xun Xiang Ji', 'Hu Nan cuisine')
Restaurant_two.describe_restaurant()
Restaurant_three = Restaurant('Qiao Jiao Niu Rou', 'Si Chuan cuisine')
Restaurant_three.describe_restaurant()
"""

# 练习9.3
"""
class User:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def describe_user(self):
        print(f"{self.first_name.title()} {self.last_name.title()} "
              f"is a student from USST.")

    def greet_user(self):
        print(f"Hello, {self.first_name.title()} {self.last_name.title()},"
              f"glad to see you!")


student_one = User('shi', 'maoqing')
student_two = User('dou', 'yamin')
student_three = User('li', 'lejun')
student_one.describe_user()
student_one.greet_user()

student_two.describe_user()
student_two.greet_user()

student_three.describe_user()
student_three.greet_user()
"""


# 9.2.2
"""
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it.")


my_new_car = Car('audi', 'a4', '2024')
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
"""


# 9.2.3-1
# 可以在定义类时，直接在__init__中给定了某个属性的值
# 而且这个属性不作为__init__的参数
# 想要修改这__init__中这个属性的值，
# Met1: 直接通过英文句点 . 对这个属性值进行修改
"""
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it.")


my_new_car = Car('audi', 'a4', '2024')
print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 30
my_new_car.read_odometer()
"""


# 9.2.3-2
# 想要修改这__init__中这个属性的值，
# Met2.1: 为了这个属性定义一个方法，
#       可以通过修改这个方法的参数来修改__init__中这个属性的值
# Met2.2: 类似于Met2.1，可以定义一个方法让属性的值递增
"""
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def get_descriptive_name(self):
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it.")

    def update_odometer(self, mileage):
        self.odometer_reading = mileage

    def increment_odometer(self, miles):
        self.odometer_reading += miles


my_new_car = Car('audi', 'a4', '2024')
print(my_new_car.get_descriptive_name())

my_new_car.update_odometer(1)
my_new_car.read_odometer()

my_new_car.increment_odometer(10)
my_new_car.read_odometer()
"""


# 9.2后的动手试一试
# 练习9.4
class Restaurant:
    def __init__(self, restaurant_name, cuisine_type):
        self.restaurant_name = restaurant_name
        self.cuisine_type = cuisine_type
        self.number_served = 0

    def describe_restaurant(self):
        print(f"{self.restaurant_name.title()} is a restaurant with {self.cuisine_type}.")

    def open_restaurant(self):
        print(f"{self.restaurant_name} is opening now!")

    def read_numOfCustomer(self):
        print(f"This restaurant has served {self.number_served} customers.")

    def set_number_served(self, volume):
        self.number_served = volume

    def increment_number_served(self, increment):
        self.number_served += increment


"""
restaurant = Restaurant('yi shan sha bao zhou', 'Hu Nan cuisine')
restaurant.read_numOfCustomer()

restaurant.number_served = 500
restaurant.read_numOfCustomer()

restaurant.set_number_served(1_000)
restaurant.read_numOfCustomer()

restaurant.increment_number_served(2_000)
restaurant.read_numOfCustomer()
"""


# 练习9.5
# 如果在__init__中写
# self.属性i = 属性i
# python中会默认创建的类中 属性i 是字符串
class User:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
        self.login_attempts = 0

    def describe_user(self):
        print(f"{self.first_name.title()} {self.last_name.title()} "
              f"is a student from USST.")

    def greet_user(self):
        print(f"Hello, {self.first_name.title()} {self.last_name.title()},"
              f"glad to see you!")

    def increment_login_attempts(self):
        self.login_attempts += 1

    def reset_login_attempts(self):
        self.login_attempts = 0


"""
user_one = User('shi', 'maoqing')
user_one.increment_login_attempts()
user_one.increment_login_attempts()
user_one.increment_login_attempts()
user_one.increment_login_attempts()
user_one.increment_login_attempts()
print(user_one.login_attempts)

user_one.reset_login_attempts()
print(user_one.login_attempts)
"""

# 9.3.1-1
# 可以在已有类的基础上，创建一个拥有更多属性和方法的类
# 此时已有类称为 父类，新的有更多属性和方法的类称为子类
"""
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        self.gas_tank_capacity = 50

    def get_descriptive_name(self):
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it.")

    def update_odometer(self, mileage):
        self.odometer_reading = mileage

    def increment_odometer(self, miles):
        self.odometer_reading += miles

    def fill_gas_tank(self):
        print(f"The tank capacity of this car is {self.gas_tank_capacity}, "
              f"if you want to fill it, it will cost {self.gas_tank_capacity * 8} RMB.")
"""

# 9.3.1-2 and 9.3.2
# 子类的初始化方法
# 下面的代码中 super().__init__(make, model, year) 的作用就是：
# 把父类中所有的方法直接放到子类中
"""
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 40

    def describe_battery(self):
        print(f"This car has a {self.battery_size}-kwh battery.")


my_leaf = ElectricCar('Geely', '\ji ke 001\\', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.describe_battery()
my_leaf.fill_gas_tank()
"""


# 9.3.3
# 重写父类的方法，可以在子类中重新定义一个与父类相同名称的方法
"""
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 40

    def describe_battery(self):
        print(f"This car has a {self.battery_size}-kwh battery.")

    def fill_gas_tank(self):
        print("This car does not have a gas tank!")


my_leaf = ElectricCar('Geely', '\ji ke 001\\', 2024)
print(my_leaf.get_descriptive_name())
my_leaf.describe_battery()
my_leaf.fill_gas_tank()
"""


# 9.3.4
# 将实例用作属性
# 定义一个类时，比如创建一个名为ElectricCar的类，可以有：
#   1、如上所属，利用super()方法进行  类的继承
#   2、在ElectricCar类中，添加一个属性，假设这个新属性的名称是battery
#      这个属性直接调用了其它类，在如下的代码中就是调用了一个名叫Battery的类
#      调用这个类后，将其值(也就是实例)，直接赋值给 ElectricCar类 中的新建的属性
#   3、想要使用Battery中的方法，应该：
#      step1: 调用ElectricCar类，创建一个ElectricCar的实例，假设名叫 my_car
#      step2: 通过 my_car.battery.describe_battery
#      即ElectricCar类的实例.ElectricCar中接收了Battery类的实例的属性battery.Battery中的方法
"""
class Battery:
    def __init__(self, battery_size=40):
        self.battery_size = battery_size

    def describe_battery(self):
        print(f"This car has a {self.battery_size}-kwh battery.")

    def get_range(self):
        if self.battery_size == 40:
            car_range = 150
        elif self.battery_size == 65:
            car_range = 225

        print(f"This car can go about {car_range} miles on a full range.")


class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery = Battery()


my_car = ElectricCar('Lamborghini', 'Murcielago', 2001)
print(my_car.get_descriptive_name())
my_car.battery.describe_battery()
my_car.battery.get_range()
"""


# 9.3后的动手试一试
# 练习9.6
class IceCreamStand(Restaurant):
    def __init__(self, restaurant_name, cuisine_type):
        super().__init__(restaurant_name, cuisine_type)
        # self.flavors = ['chocolate', 'cream', 'matcha', 'coffee']
        self.flavors = []

    def show_flavors(self, condiments):
        while condiments:
            condiment = condiments.pop(0)
            self.flavors.append(condiment)

        print(f"This ice cream stand makes ice cream with the following flavors:")
        while self.flavors:
            print(f"{self.flavors.pop(0)}")


IceCreamStand_One = IceCreamStand('Mi Xue Bing Cheng', 'milk tea')
IceCreamStand_One.read_numOfCustomer()

IceCreamStand_One.number_served = 5_000
IceCreamStand_One.read_numOfCustomer()

IceCreamStand_One.set_number_served(10_000)
IceCreamStand_One.read_numOfCustomer()

IceCreamStand_One.increment_number_served(20_000)
IceCreamStand_One.read_numOfCustomer()

flavors = ['chocolate', 'cream', 'matcha', 'coffee']
IceCreamStand_One.show_flavors(flavors[:])


# 练习9.7
"""
class Admin(User):
    def __init__(self, first_name, last_name):
        super().__init__(first_name, last_name)
        self.privileges = []

    def show_privileges(self, additional_rights):
        while additional_rights:
            additional_right = additional_rights.pop(0)
            self.privileges.append(additional_right)

        print(f"Administrator has several privileges.")
        while self.privileges:
            print(f"As a administrator, you {self.privileges.pop(0)}.")


administrator_one = Admin('shi', 'maoqing')
administrator_one.describe_user()
administrator_one.greet_user()

privileges = ['can add post', 'can delete post', 'can ban user']
administrator_one.show_privileges(privileges)
"""


# 练习9.8
"""
class Privileges:
    def __init__(self, privileges=['can add post', 'can delete post', 'can ban user']):
        self.privileges = privileges

    def show_privileges(self, additional_rights):
        if additional_rights:
            self.privileges = []
            while additional_rights:
                additional_right = additional_rights.pop(0)
                self.privileges.append(additional_right)

            print(f"Administrator has several privileges.")
            while self.privileges:
                print(f"As a administrator, you {self.privileges.pop(0)}.")

        else:
            print(f"Administrator has several privileges.")
            while self.privileges:
                print(f"As a administrator, you {self.privileges.pop(0)}.")


class Admin(User):
    def __init__(self, first_name, last_name):
        super().__init__(first_name, last_name)
        self.privileges = Privileges()


administrator_one = Admin('shi', 'maoqing')
administrator_one.describe_user()
administrator_one.greet_user()

privileges = ['can add post', 'can delete post', 'can ban user', 'can mute user']
administrator_one.privileges.show_privileges(privileges)
"""


# 练习9.9
"""
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        self.gas_tank_capacity = 50

    def get_descriptive_name(self):
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        print(f"This car has {self.odometer_reading} miles on it.")

    def update_odometer(self, mileage):
        self.odometer_reading = mileage

    def increment_odometer(self, miles):
        self.odometer_reading += miles

    def fill_gas_tank(self):
        print(f"The tank capacity of this car is {self.gas_tank_capacity}, "
              f"if you want to fill it, it will cost {self.gas_tank_capacity * 8} RMB.")
"""

"""
class Battery:
    def __init__(self, battery_size=40):
        self.battery_size = battery_size

    def describe_battery(self):
        print(f"This car has a {self.battery_size}-kwh battery.")

    def get_range(self):
        if self.battery_size == 40:
            car_range = 150
        elif self.battery_size == 65:
            car_range = 225

        print(f"This car can go about {car_range} miles on a full range.")

    def upgrade_battery(self):
        if self.battery_size != 65:
            self.battery_size = 65


class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery = Battery()


my_car = ElectricCar('Lamborghini', 'Murcielago', 2001)
print(my_car.get_descriptive_name())

my_car.battery.get_range()
my_car.battery.describe_battery()

my_car.battery.upgrade_battery()
my_car.battery.get_range()
my_car.battery.describe_battery()
"""

"""
from car import ElectricCar
my_car = ElectricCar('Lamborghini', 'Murcielago', 2001)
print(my_car.get_descriptive_name())
my_car.battery.describe_battery()
my_car.battery.get_range()
"""

# 9.5
"""
from random import randint
from random import choice
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))
print(randint(1, 6))


players = ['charles', 'martina', 'michael', 'florence', 'eli']
first_up = choice(players)
print(first_up)
"""


# 9.5后的动手试一试
# 练习9.13
"""
from random import randint
class Die:
    def __init__(self, sides=6):
        self.sides = sides

    def roll_die(self):
        return randint(1, self.sides)


results = []
dice_with_six_sides = Die()
for roll_num in range(10):
    result = dice_with_six_sides.roll_die()
    results.append(result)

print(f"The dice has six sides.")
print(results)

results = []
dice_with_ten_sides = Die()
for roll_num in range(10):
    result = dice_with_ten_sides.roll_die()
    results.append(result)

print(f"The dice has ten sides.")
print(results)
"""

# 练习9.14
from random import choice
"""
numberOrAlphabet = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                    'a', 'b', 'c', 'd', 'e']

win_ticket = []
while len(win_ticket) < 4:
    one_winning_num = choice(numberOrAlphabet)
    if one_winning_num not in win_ticket:
        win_ticket.append(one_winning_num)

print(f"If there is {win_ticket} in your ticket, you could receive the bonus.")
"""


# 练习9.15
def random_win_ticket(numberOrAlphabet):
    win_ticket = []
    while len(win_ticket) < 9:
        one_winning_num = choice(numberOrAlphabet)
        if one_winning_num not in win_ticket:
            win_ticket.append(one_winning_num)

    return win_ticket


def random_my_ticket(numberOrAlphabet):
    my_ticket = []
    while len(my_ticket) < 9:
        one_winning_num = choice(numberOrAlphabet)
        if one_winning_num not in my_ticket:
            my_ticket.append(one_winning_num)

    return my_ticket


def win_check(win_ticket, my_ticket):
    for i in range(9):
        if my_ticket[i] not in win_ticket:
            return False
    return True


numberOrAlphabet = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                    'a', 'b', 'c', 'd', 'e']
win_ticket = random_win_ticket(numberOrAlphabet)

numOfLottery = 0
win_flag = 0

maximum_attempts = 5_000

while not win_flag:
    my_ticket = random_my_ticket(numberOrAlphabet)
    win_flag = win_check(win_ticket, my_ticket)
    numOfLottery += 1
    if numOfLottery >= maximum_attempts:
        break

if win_flag:
    print(f"We have tried {numOfLottery} times, we won at the last time!")
    print(f"Your ticket: {my_ticket}")
    print(f"Win ticket: {win_ticket}")
else:
    print(f"We have tried {numOfLottery} times, we have not won the lottery.")


